package com.lagou.edu.users.filter;

import com.lagou.edu.users.config.FlushBrushPathBean;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.io.UnsupportedEncodingException;

/**
 * 防暴刷过滤器
 */
@Component
public class FlushBrushFilter implements GlobalFilter, Ordered {

    @Autowired
    private FlushBrushPathBean flushBrushPathBean;

    private String filterPath = "/api/user/register/**";

    private PathMatcher matcher = new AntPathMatcher();

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        // 获取请求路径
        String path = request.getURI().getPath();

        // 判断请求是否为注册/api/user/register/**
        if(match(filterPath,path)){
            String host = request.getRemoteAddress().getHostString();
            boolean granted = flushBrushPathBean.isGranted(host);
            if (!granted){
                //表示漏斗溢出，抛出303错误
                return oftenHandle(response);
            }
        }

        return chain.filter(exchange);
    }

    private boolean match(String patternUrl, String requestUrl){
        if (StringUtils.isEmpty(patternUrl) || StringUtils.isEmpty(requestUrl)){
            return false;
        }
        return matcher.match(patternUrl, requestUrl);
    }

    private Mono<Void> oftenHandle(ServerHttpResponse response){
        response.setStatusCode(HttpStatus.SEE_OTHER);//状态码，未认证

        // 这里都是使用WebFluxAPI进行写操作。
        String data = "您频繁进行注册，请求被拒绝。";
        DataBuffer wrap = null;
        try {
            response.getHeaders().add("Content-Type","text/plain; charset=utf-8");
            wrap = response.bufferFactory().wrap(data.getBytes("UTF-8"));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        return response.writeWith(Mono.just(wrap));
    }

    @Override
    public int getOrder() {
        return -1;
    }
}
